﻿' ref: http://d.hatena.ne.jp/MillyC/20080312/1205311545

Public Class CenterMessageBox

    Private Shared HookHandle As IntPtr = IntPtr.Zero
    Private Shared OwnerHandle As IntPtr = IntPtr.Zero

    Public Shared Function Show(ByVal owner As Window, _
                           ByVal messageboxText As String, _
                           Optional ByVal caption As String = "", _
                           Optional ByVal button As MessageBoxButton = MessageBoxButton.OK, _
                           Optional ByVal icon As MessageBoxImage = MessageBoxImage.None, _
                           Optional ByVal defaultResult As MessageBoxResult = MessageBoxResult.None, _
                           Optional ByVal options As Windows.MessageBoxOptions = Windows.MessageBoxOptions.None) As MessageBoxResult

        OwnerHandle = New System.Windows.Interop.WindowInteropHelper(owner).Handle()
        Dim hInstance = NativeMethods.GetWindowLong(OwnerHandle, NativeMethods.GWL_HINSTANCE)
        Dim threadId = NativeMethods.GetCurrentThreadId()
        HookHandle = NativeMethods.SetWindowsHookEx(NativeMethods.WH_CBT, AddressOf HookProc, hInstance, threadId)

        Return MessageBox.Show(messageboxText, caption, button, icon, defaultResult, options)

    End Function

    Private Shared Function HookProc(ByVal nCode As Integer, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntPtr

        If nCode = NativeMethods.HCBT_ACTIVATE Then
            Dim ownerRect As NativeMethods.RECT
            Dim messageBoxRect As NativeMethods.RECT

            NativeMethods.GetWindowRect(OwnerHandle, ownerRect)
            NativeMethods.GetWindowRect(wParam, messageBoxRect)

            Dim x = ownerRect.Left + (ownerRect.Width - messageBoxRect.Width) \ 2
            Dim y = ownerRect.Top + (ownerRect.Height - messageBoxRect.Height) \ 2

            NativeMethods.SetWindowPos(wParam, 0, x, y, 0, 0, _
                NativeMethods.SWP_NOSIZE Or NativeMethods.SWP_NOZORDER Or NativeMethods.SWP_NOACTIVATE)

            Try
                Return NativeMethods.CallNextHookEx(CenterMessageBox.HookHandle, nCode, wParam, lParam)
            Finally
                NativeMethods.UnhookWindowsHookEx(CenterMessageBox.HookHandle)
                CenterMessageBox.HookHandle = IntPtr.Zero
            End Try
        End If

        Return NativeMethods.CallNextHookEx(CenterMessageBox.HookHandle, nCode, wParam, lParam)
    End Function

    Private Sub New()
    End Sub
End Class
